# -*- coding: UTF-8 -*-
'''
Created on 18.06.2014

@author: MathiasAr
'''

import Image, os, sys
from ImageHelper import AutoOrientImage, CropResize
from types import FunctionType
import random

def imagePuzzle(im, tileSize, puzzleSize, puzzleList, noDouble=False, update_callback=None, user_data=None):
    """imagePuzzle() --> Image from PIL
    
    im: image to make a puzzle of
    tileSize: count of pixel to build one puzzle
    puzzleSize: dimension of one puzzle
    puzzleList: list with puzzle images
    noDouble: each puzzle part is unique
    update_callback: function to call when a processing step is done
    user_data: object that will passed to the callback
    """
    
    # load the source image
    srcIm = im.convert("L")
    puzzleSize = int(puzzleSize)
    tileSize = int(tileSize)
    
    # load puzzle parts
    puzzleIms = []
    puzzleColors = []
    proceed = 0
    for pf in puzzleList:
        try:
            proceed += 1
            im = Image.open(pf, "r")
            im = im.convert("RGB")
            im = AutoOrientImage(im, pf)
            im = CropResize(im, (puzzleSize, puzzleSize))
            puzzleIms.append((im, pf))
            colorIm = im.resize((1, 1), Image.ANTIALIAS)
            colorIm = colorIm.convert("L")
        except:
            continue
        puzzleColors.append(colorIm.getpixel((0, 0)))
        # update callback
        if type(update_callback) is FunctionType:
                result = update_callback(user_data, (float(proceed) / (float(len(puzzleList)))) * 50.0)
                if (result != None and result != 0):
                    return None
    
    # resize source image to multiples of tile-size
    srcSizeX = int(srcIm.size[0] / tileSize)
    srcSizeY = int(srcIm.size[1] / tileSize)
    srcIm = CropResize(srcIm, (srcSizeX, srcSizeY))
    
    # load the pixel data
    srcPix = srcIm.load()
    
    # create the new puzzle image
    newIm = Image.new("RGB", (srcSizeX * puzzleSize, srcSizeY * puzzleSize), 0)
    
    for y in range(srcIm.size[1]):
        for x in range(srcIm.size[0]):
            pix = srcPix[x, y]
            match = -1
            minDiff = 256
            index = range(len(puzzleColors))
            random.seed()
            while len(index) > 0:
                if noDouble:
                    i = random.randint(0, len(index) - 1)
                else:
                    i = 0
                i = index.pop(i)
                d = abs(puzzleColors[i] - pix)
                if d < minDiff:
                    minDiff = d
                    match = i 
                pass
            if match >= 0:
                im = puzzleIms[match][0]
                posX = x * puzzleSize
                posY = y * puzzleSize
                toX = posX + im.size[0]
                toY = posY + im.size[1]
                # add new puzzle image
                pf = puzzleIms[match][1]
                newIm.paste(im, (posX, posY, toX, toY))
                if noDouble:
                    puzzleColors.pop(match)
                    puzzleIms.pop(match)
            if type(update_callback) is FunctionType:
                result = update_callback(user_data, 50 + (float(y + 1) / float(srcIm.size[1])) * 50)
                if (result != None and result != 0):
                    return newIm
            pass
        pass
    return newIm




if __name__ == '__main__':
  
    imageList = []
    
    images = u"/home/mathias/Bilder/2014/2014-05-14_Kitaausflug_Germendorf/sorted_oriented/"
    image = u"/home/mathias/Bilder/2014/2014-05-14_Kitaausflug_Germendorf/kdenlive/Images/logo_120x110.jpg"
    
    for f in os.listdir(images):
        if os.path.isfile(images + f):
            ext = os.path.splitext(f)[-1].lower()
            if (ext == '.jpg' or ext == '.jpeg' or ext == '.png' or ext == '.bmp'):
                imageList.append(images + f)
    
    print str(len(imageList)) + " image(s) found"
    
    if len(imageList) <= 0:
        sys.exit(1)
    
    imagePuzzle(Image.open(image, 'r'), 20, imageList, False).save(u"/home/mathias/Desktop/test.jpg")
    pass
